# SPDX-License-Identifier: Apache-2.0
"""
Observations

Revision ID: 4297620f7b41
Revises: 186f076eb60b
Create Date: 2023-10-31 21:56:51.280480
"""

import sqlalchemy as sa

from alembic import op
from sqlalchemy.dialects import postgresql

revision = "4297620f7b41"
down_revision = "b34fa465a67c"

# Note: It is VERY important to ensure that a migration does not lock for a
#       long period of time and to ensure that each individual migration does
#       not break compatibility with the *previous* version of the code base.
#       This is because the migrations will be ran automatically as part of the
#       deployment process, but while the previous version of the code is still
#       up and running. Thus backwards incompatible changes must be broken up
#       over multiple migrations inside of multiple pull requests in order to
#       phase them in over multiple deploys.
#
#       By default, migrations cannot wait more than 4s on acquiring a lock
#       and each individual statement cannot take more than 5s. This helps
#       prevent situations where a slow migration takes the entire site down.
#
#       If you need to increase this timeout for a migration, you can do so
#       by adding:
#
#           op.execute("SET statement_timeout = 5000")
#           op.execute("SET lock_timeout = 4000")
#
#       To whatever values are reasonable for this migration as part of your
#       migration.


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "observer_association",
        sa.Column(
            "discriminator",
            sa.String(),
            nullable=False,
            comment="The type of the parent",
        ),
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "observers",
        sa.Column(
            "created", sa.DateTime(), server_default=sa.text("now()"), nullable=False
        ),
        sa.Column("_association_id", sa.UUID(), nullable=True),
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["_association_id"],
            ["observer_association.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "project_observations",
        sa.Column(
            "related_id",
            sa.UUID(),
            nullable=False,
            comment="The ID of the related model",
        ),
        sa.Column(
            "observer_id",
            sa.UUID(),
            nullable=False,
            comment="ID of the Observer who created the Observation",
        ),
        sa.Column(
            "created",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
            comment="The time the observation was created",
        ),
        sa.Column(
            "kind", sa.String(), nullable=False, comment="The kind of observation"
        ),
        sa.Column(
            "summary",
            sa.String(),
            nullable=False,
            comment="A short summary of the observation",
        ),
        sa.Column(
            "payload",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=False,
            comment="The observation payload we received",
        ),
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["observer_id"],
            ["observers.id"],
        ),
        sa.ForeignKeyConstraint(
            ["related_id"],
            ["projects.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_project_observations_related_id"),
        "project_observations",
        ["related_id"],
        unique=False,
    )
    op.create_table(
        "release_observations",
        sa.Column(
            "related_id",
            sa.UUID(),
            nullable=False,
            comment="The ID of the related model",
        ),
        sa.Column(
            "observer_id",
            sa.UUID(),
            nullable=False,
            comment="ID of the Observer who created the Observation",
        ),
        sa.Column(
            "created",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
            comment="The time the observation was created",
        ),
        sa.Column(
            "kind", sa.String(), nullable=False, comment="The kind of observation"
        ),
        sa.Column(
            "summary",
            sa.String(),
            nullable=False,
            comment="A short summary of the observation",
        ),
        sa.Column(
            "payload",
            postgresql.JSONB(astext_type=sa.Text()),
            nullable=False,
            comment="The observation payload we received",
        ),
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.ForeignKeyConstraint(
            ["observer_id"],
            ["observers.id"],
        ),
        sa.ForeignKeyConstraint(
            ["related_id"],
            ["releases.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_release_observations_related_id"),
        "release_observations",
        ["related_id"],
        unique=False,
    )
    op.add_column(
        "users", sa.Column("observer_association_id", sa.UUID(), nullable=True)
    )
    op.create_foreign_key(
        None, "users", "observer_association", ["observer_association_id"], ["id"]
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint(None, "users", type_="foreignkey")
    op.drop_column("users", "observer_association_id")
    op.drop_index(
        op.f("ix_release_observations_related_id"), table_name="release_observations"
    )
    op.drop_table("release_observations")
    op.drop_index(
        op.f("ix_project_observations_related_id"), table_name="project_observations"
    )
    op.drop_table("project_observations")
    op.drop_table("observers")
    op.drop_table("observer_association")
    # ### end Alembic commands ###
